#pragma once

#include "Socket.hpp"
#include <iostream>
#include <pthread.h>
#include <functional>

using func_t = std::function<std::string(std::string &, bool *error_code)>; // &必须的

class Tcpserver;

class ThreadData
{
public:
    ThreadData(Tcpserver* tcp_this, Net_Work::Socket* sockp)
    :_this(tcp_this), _sockp(sockp)
    {}
public:    
    Tcpserver* _this;
    Net_Work::Socket* _sockp;
};

class Tcpserver
{
public:
    Tcpserver(uint16_t port, func_t handler_request)
    :_port(port), _handler_request(handler_request), _listensocket(new Net_Work::TcpSocket())
    {
        _listensocket->BuildListenSocketMethod(_port, Net_Work::backlog);
    }
    static void* Threadrun(void* args)
    {
        pthread_detach(pthread_self());
        ThreadData* td = static_cast<ThreadData*>(args);
        std::string inbufferstream;
        while(true){
            bool ok = true;
            if(!td->_sockp->Recv(&inbufferstream, 1024))break;
            std::string send_string = td->_this->_handler_request(inbufferstream,&ok);
            if(ok){
                if(!send_string.empty()){
                    td->_sockp->Send(send_string);
                }
            }else break;
        }
        td->_sockp->CloseSockfd();
        delete td->_sockp;
        delete td;
        return nullptr;
    }
    void loop()
    {
        while(true)
        {
            std::string peerip;
            uint16_t peerport;
            Net_Work::Socket* newsock = _listensocket->AcceptConnection(&peerip, &peerport);
            if(newsock == nullptr){
                continue;
            }
            std::cout << "获取一个新连接, sockfd: " << newsock->GetSockfd() << " client info: " << peerip << ":" << peerport << std::endl;
            pthread_t tid;
            ThreadData* td = new ThreadData(this, newsock);
            pthread_create(&tid, NULL, Threadrun, td); 
        }
    }
    ~Tcpserver(){
        delete _listensocket;
    }
private:
    uint16_t _port;
    Net_Work::Socket* _listensocket;
public:
    func_t _handler_request;
};